<?php
/**
 * Handles all Products of an Order using data from the Order Data Transfer Object and the Zen Cart Database.
 * @copyright Nicolas Schudel 2008
 * @copyright Portions Copyright 2003-2006 Zen Cart Development Team
 * @copyright Portions Copyright 2003 osCommerce
 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
 */

require_once(DTO_PATH . 'OrderDTO.php');
require_once(INTERFACES_PATH . 'IOrderable.php');

class OrdersProducts implements IOrderable{
	private $db;
	private $cf;
	private $taxes;
	private $ordersProducts;
	
	function __construct() {
		$this->db = ServiceLocator::getService('ConnectionFactory');
		$this->cf = ServiceLocator::getService('Configuration');
		$this->taxes = ServiceLocator::getService('Taxes');
		$this->prices = ServiceLocator::getService('Prices');
		
		$this->db->connect($this->cf->get('DB_SERVER'), $this->cf->get('DB_SERVER_USERNAME'), $this->cf->get('DB_SERVER_PASSWORD'), $this->cf->get('DB_DATABASE'), $this->cf->get('DB_USE_PCONNECT'), false);
	}
	
	private function filterDuplicateOrdersProducts() {
		// make sure each quantity value is set to at least 1
		foreach ($this->dto->products as $pkey => $p) if (is_null($p->qty)) $p->qty = 1;
		
		
		// add up duplicates and put them in a new array
		$clean_array = array();
		foreach ($this->dto->products as $pkey => $p) {
			
			foreach($this->dto->products as $dkey => $d) {
				if ($p->pid == $d->pid && $pkey != $dkey && $p->qty != -1) {
					$p->qty += $d->qty;
					$d->qty = -1;
				}
			}
			
			if ($p->qty != -1) array_push($clean_array, $p);
		}
		
		$this->dto->products = $clean_array;
	}
	
	public function find($pid){
		return "not implemented yet";
	}
	
	public function load(OrderDTO $dto) {
		if (!isset($dto)) throw new Exception ("OrderDTO not set");
		$this->dto = $dto;
		
		$this->filterDuplicateOrdersProducts();
		$this->ordersProducts = array();
		
		foreach ($this->dto->products as $p) {
			// get the need information fromthe db base in the ids
			$products_query = "select p.products_id, p.master_categories_id, p.products_status, 
								pd.products_name, p.products_model, p.products_image,
								p.products_price, p.products_weight, p.products_tax_class_id,
								p.products_quantity_order_min, p.products_quantity_order_units,
								p.product_is_free, p.products_priced_by_attribute,
								p.products_discount_type, p.products_discount_type_from
								from " . $this->cf->get('TABLE_PRODUCTS') . " p, " . $this->cf->get('TABLE_PRODUCTS_DESCRIPTION') . " pd
								where p.products_id = '" . (int)$p->pid . "'
								and pd.products_id = p.products_id
								and pd.language_id = '" . (int)$this->cf->get('POS_DEFAULT_LANGUAGE_ID') . "'";
			$productTables = $this->db->execute($products_query);
			
			// insert the attibutes
			$product = 		array('id' => $p->pid,
								'category' => $productTables->fields['master_categories_id'],
								'name' => $productTables->fields['products_name'],
								'model' => $productTables->fields['products_model'],
								'image' => $productTables->fields['products_image'],
								'price' => $this->prices->getPrice($p->pid),
								'qty' => $p->qty,
								'weight' => $productTables->fields['products_weight'],
								'final_price' => $productTables->fields['products_price'],
								'onetime_charges' => 0,
								'tax_class_id' => $productTables->fields['products_tax_class_id'],
								'tax' => ($this->cf->get('DISPLAY_PRICE_WITH_TAX') == 'true' ? $this->taxes->getTaxRate($productTables->fields['products_tax_class_id']) : 0),
								'tax_description' => $this->taxes->getTaxDescription($productTables->fields['products_tax_class_id']),
								'attributes' => $p->options,
								'attributes_values' => $p->options,
								'products_priced_by_attribute' => $productTables->fields['products_priced_by_attribute'],
								'product_is_free' => $productTables->fields['product_is_free'],
								'products_discount_type' => $productTables->fields['products_discount_type'],
								'products_discount_type_from' => $productTables->fields['products_discount_type_from']
								);
							
			array_push($this->ordersProducts, $product);
		}
		
		/* Gather the product attributes */
		
		$index = 0;
		for ($i=0, $n=sizeof($this->ordersProducts); $i<$n; $i++) {
			if ($this->ordersProducts[$i]['attributes']) {
				reset($this->ordersProducts[$i]['attributes']);
				for ($j=0, $a=sizeof($this->ordersProducts[$i]['attributes']); $j<$a; $j++) {
					$productOption = $this->ordersProducts[$i]['attributes'][$j];

					$attributes_query = "select popt.products_options_name, poval.products_options_values_name,
									pa.options_values_price, pa.price_prefix
									from " . $this->cf->get('TABLE_PRODUCTS_OPTIONS') . " popt,
									" . $this->cf->get('TABLE_PRODUCTS_OPTIONS_VALUES') . " poval,
									" . $this->cf->get('TABLE_PRODUCTS_ATTRIBUTES') . " pa
									where pa.products_id = '" . (int)$this->ordersProducts[$i]['id'] . "'
									and pa.options_id = '" . (int)$productOption->options_id . "'
									and pa.options_id = popt.products_options_id
									and pa.options_values_id = '" . (int)$productOption->options_values_id . "'
									and pa.options_values_id = poval.products_options_values_id
									and popt.language_id = '" . (int)$this->cf->get('POS_DEFAULT_LANGUAGE_ID') . "'
									and poval.language_id = '" . (int)$this->cf->get('POS_DEFAULT_LANGUAGE_ID') . "'";
					
					$attributes = $this->db->execute($attributes_query);
		
					if ($productOption->options_values_id == $this->cf->get('PRODUCTS_OPTIONS_VALUES_TEXT_ID')){
						$attr_value = $this->ordersProducts[$i]['attributes_values'][$option];
					} else {
						$attr_value = $attributes->fields['products_options_values_name'];
					}
		
					$this->ordersProducts[$i]['attributes'][$j] = array('option' => $attributes->fields['products_options_name'],
																			'value' => $attr_value,
																			'option_id' => $productOption->options_id,
																			'value_id' => $productOption->options_values_id,
																			'prefix' => $attributes->fields['price_prefix'],
																			'price' => $attributes->fields['options_values_price']
																			);
		
				}
			}
			$index++;
		}
		return $this->ordersProducts;
	}
	
	function save($insert_id) {
		if (empty($insert_id)) throw new Exception("The Insertion ID is not defined");
		
		for ($i=0, $n=sizeof($this->ordersProducts); $i<$n; $i++) {

			if ($this->cf->get('STOCK_LIMITED') == 'true') {
				$stock_values = $this->db->execute("select products_quantity, product_is_always_free_shipping  from " . $this->cf->get('TABLE_PRODUCTS') . " where products_id = '" . $this->ordersProducts[$i]['id'] . "'");
			
				if ($stock_values->fields['product_is_always_free_shipping'] != 2 ) {
					$stock_left = $stock_values->fields['products_quantity'] - $this->ordersProducts[$i]['qty'];
					$this->ordersProducts[$i]['stock_reduce'] = $this->ordersProducts[$i]['qty'];
				} else {
					$stock_left = $stock_values->fields['products_quantity'];
				}
				
				$this->db->execute("update " . $this->cf->get('TABLE_PRODUCTS') . " set products_quantity = '" . $stock_left . "' where products_id = '" . $this->ordersProducts[$i]['id'] . "'");
			
				if ($stock_left <= 0) {
					if ($this->cf->get('SHOW_PRODUCTS_SOLD_OUT') == '0') {
						$this->db->execute("update " . $this->cf->get('TABLE_PRODUCTS') . " set products_status = 0 where products_id = '" . $this->ordersProducts[$i]['id'] . "'");
					}
				}
			}
	
			$this->db->execute("update " . $this->cf->get('TABLE_PRODUCTS') . " set products_ordered = products_ordered + " . sprintf('%f', $this->ordersProducts[$i]['qty']) . " where products_id = '" . $this->ordersProducts[$i]['id'] . "'");
			
			$sql_data_array = array('orders_id' => $insert_id,
									'products_id' => $this->ordersProducts[$i]['id'],
									'products_model' => $this->ordersProducts[$i]['model'],
									'products_name' => $this->ordersProducts[$i]['name'],
									'products_price' => $this->ordersProducts[$i]['price'],
									'final_price' => $this->ordersProducts[$i]['final_price'],
									'onetime_charges' => $this->ordersProducts[$i]['onetime_charges'],
									'products_tax' => $this->ordersProducts[$i]['tax'],
									'products_quantity' => $this->ordersProducts[$i]['qty'],
									'products_priced_by_attribute' => $this->ordersProducts[$i]['products_priced_by_attribute'],
									'product_is_free' => $this->ordersProducts[$i]['product_is_free'],
									'products_discount_type' => $this->ordersProducts[$i]['products_discount_type'],
									'products_discount_type_from' => $this->ordersProducts[$i]['products_discount_type_from'],
									'products_prid' => $this->ordersProducts[$i]['id']
									);
			$this->db->perform($this->cf->get('TABLE_ORDERS_PRODUCTS'), $sql_data_array);
		
			$order_products_id = $this->db->Insert_ID();
	
			$attributes_exist = '0';
			if (isset($this->ordersProducts[$i]['attributes'])) {
				$attributes_exist = '1';

				for ($j=0, $n2=sizeof($this->ordersProducts[$i]['attributes']); $j<$n2; $j++) {
					
					$attributes_values = $this->db->execute("select popt.products_options_name, poval.products_options_values_name,
										pa.options_values_price, pa.price_prefix,
										pa.product_attribute_is_free, pa.products_attributes_weight, pa.products_attributes_weight_prefix,
										pa.attributes_discounted, pa.attributes_price_base_included, pa.attributes_price_onetime,
										pa.attributes_price_factor, pa.attributes_price_factor_offset,
										pa.attributes_price_factor_onetime, pa.attributes_price_factor_onetime_offset,
										pa.attributes_qty_prices, pa.attributes_qty_prices_onetime,
										pa.attributes_price_words, pa.attributes_price_words_free,
										pa.attributes_price_letters, pa.attributes_price_letters_free
										from " . $this->cf->get('TABLE_PRODUCTS_OPTIONS') . " popt, " . $this->cf->get('TABLE_PRODUCTS_OPTIONS_VALUES') . " poval, " . $this->cf->get('TABLE_PRODUCTS_ATTRIBUTES') . " pa
										where pa.products_id = '" . $this->ordersProducts[$i]['id'] . "' and pa.options_id = '" . (int)$this->ordersProducts[$i]['attributes'][$j]['option_id'] . "' 
										and pa.options_id = popt.products_options_id and pa.options_values_id = '" . (int)$this->ordersProducts[$i]['attributes'][$j]['value_id'] . "' 
										and pa.options_values_id = poval.products_options_values_id and popt.language_id = '" . (int)$this->cf->get('POS_DEFAULT_LANGUAGE_ID') . "' 
										and poval.language_id = '" . (int)$this->cf->get('POS_DEFAULT_LANGUAGE_ID') . "'");
			
					$sql_data_array = array('orders_id' => $insert_id,
										'orders_products_id' => $order_products_id,
										'products_options' => $attributes_values->fields['products_options_name'],
										'products_options_values' => $this->ordersProducts[$i]['attributes'][$j]['value'],
										'options_values_price' => $attributes_values->fields['options_values_price'],
										'price_prefix' => $attributes_values->fields['price_prefix'],
										'product_attribute_is_free' => $attributes_values->fields['product_attribute_is_free'],
										'products_attributes_weight' => $attributes_values->fields['products_attributes_weight'],
										'products_attributes_weight_prefix' => $attributes_values->fields['products_attributes_weight_prefix'],
										'attributes_discounted' => $attributes_values->fields['attributes_discounted'],
										'attributes_price_base_included' => $attributes_values->fields['attributes_price_base_included'],
										'attributes_price_onetime' => $attributes_values->fields['attributes_price_onetime'],
										'attributes_price_factor' => $attributes_values->fields['attributes_price_factor'],
										'attributes_price_factor_offset' => $attributes_values->fields['attributes_price_factor_offset'],
										'attributes_price_factor_onetime' => $attributes_values->fields['attributes_price_factor_onetime'],
										'attributes_price_factor_onetime_offset' => $attributes_values->fields['attributes_price_factor_onetime_offset'],
										'attributes_qty_prices' => $attributes_values->fields['attributes_qty_prices'],
										'attributes_qty_prices_onetime' => $attributes_values->fields['attributes_qty_prices_onetime'],
										'attributes_price_words' => $attributes_values->fields['attributes_price_words'],
										'attributes_price_words_free' => $attributes_values->fields['attributes_price_words_free'],
										'attributes_price_letters' => $attributes_values->fields['attributes_price_letters'],
										'attributes_price_letters_free' => $attributes_values->fields['attributes_price_letters_free'],
										'products_options_id' => (int)$this->ordersProducts[$i]['attributes'][$j]['option_id'],
										'products_options_values_id' => (int)$this->ordersProducts[$i]['attributes'][$j]['value_id'],
										'products_prid' => $this->ordersProducts[$i]['id']
										);
					$this->db->perform($this->cf->get('TABLE_ORDERS_PRODUCTS_ATTRIBUTES'), $sql_data_array);
				}
			}
		}
	}
	
}
?>
